import datetime
import os

from django.db import transaction
from django.db.models import Q, F
from django.http import HttpResponse, StreamingHttpResponse, FileResponse
from django.shortcuts import render, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView

from helloWorld.forms import StudentForm, BookInfoForm, BookInfoModelForm
from helloWorld.models import StudentInfo, BookInfo, BookTypeInfo, AccountInfo


# Create your views here.
def index2(request):
    str = "hello"
    date = datetime.datetime.now()
    myDict = {"tom": '666', 'cat': '999', 'wzw': '333'}
    # 创建一个对象 zhangsan
    zhangsan = Person("张三", 21)
    myList = ["java", "python", "c"]
    myTuple = ("python", 222, 3.14, False)
    content_value = {"msg": str, "msg2": myDict, "msg3": zhangsan, "msg4":
        myList, "msg5": myTuple, "date": date}
    return render(request, 'index2.html', context=content_value)


def blog(request, id):
    if id == 0:
        return redirect("/static/error.html")
    else:
        return HttpResponse('id是' + str(id) + "的博客页面")


def blog2(request, year, month, day, id):
    return HttpResponse(
        'id是' + str(id) + "的博客页面，发布时间是" + str(year) + "年" + str(month) + "月" + str(day) + "日")


# 定义文件路径
file_path = "D:\\mysql-9.5.0.msi"


def to_login(request):
    """
    跳转登录页面
    :param request:
    :return:
    """
    return render(request, 'login.html')


def login(request):
    """
    登录
    :param request:
    :return:
    """
    user_name = request.POST.get("user_name")
    pwd = request.POST.get("pwd")
    if user_name == 'python222' and pwd == '123456':
        request.session['currentUserName'] = user_name  # session中存一个用户名
        print('session获取', request.session['currentUserName'])
        response = render(request, 'main.html')  # 获取HttpResponse
        response.set_cookie("remember_me", True)  # 设置cookie
        response.set_cookie("test_key", "test_value")
        return response
    else:
        content_value = {"error_info": '用户名或者密码错误！'}
        return render(request, 'login.html', context=content_value)


def download_file1(request):
    file = open(file_path, 'rb')  # 打开文件
    response = HttpResponse(file)  # 创建HttpResponse对象
    response['Content_Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename=file1.msi'
    return response


def download_file2(request):
    file = open(file_path, 'rb')  # 打开文件
    response = StreamingHttpResponse(file)  # 创建StreamingHttpResponse对象
    response['Content_Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename=file2.msi'
    return response


def download_file3(request):
    file = open(file_path, 'rb')  # 打开文件
    response = FileResponse(file)  # 创建FileResponse对象
    response['Content_Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename=file3.msi'
    return response


def get_test(request):
    """
    get请求测试
    :param request:
    :return:
    """
    print("get请求测试 ", "请求方式：", request.method)  # 请求方式
    # 常用属性
    print("get请求测试 ", "请求头Content-Type：", request.content_type)
    print("get请求测试 ", "请求头Content-Params：", request.content_params)
    print("get请求测试 ", "请求头COOKIES：", request.COOKIES)
    print("get请求测试 ", "请求头scheme：", request.scheme)
    # 常用方法
    print("get请求测试 ", "是否是安全连接：", request.is_secure())
    print("get请求测试 ", "主机名：", request.get_host())
    print("get请求测试 ", "完整路径：", request.get_full_path())
    print("get请求测试 ", "GET参数name：", request.GET.get("name"))
    print("get请求测试 ", "GET参数pwd：", request.GET.get("pwd"))
    print("get请求测试 ", "GET参数aaa：", request.GET.get("aaa", "666"))
    return HttpResponse("http get ok")


def post_test(request):
    """
    post请求测试
    :param request:
    :return:
    """
    print("post请求测试 ", "请求方式：", request.method)  # 请求方式
    print("post请求测试 ", "POST参数name：", request.POST.get("name"))
    print("post请求测试 ", "POST参数pwd：", request.POST.get("pwd"))
    print("post请求测试 ", "POST参数aaa：", request.POST.get("aaa", "666"))
    return HttpResponse("http post ok")


def to_upload(request):
    """
    跳转文件上传页面
    :param request:
    :return:
    """
    return render(request, 'upload.html')


def upload(request):
    """
    文件上传
    :param request:
    :return:
    """
    # 获取上传的文件，如果没有文件，就默认为None
    my_file = request.FILES.get("my_file", None)
    if my_file:
        # 检查是否在存Download目录下
        if not os.path.exists("D:\\Download"):
            os.makedirs("D:\\Download")
        # 打开特定的文件进行二进制的写操作
        f = open(os.path.join("D:\\Download", my_file.name), "wb+")
        # 分块写入文件
        for chunk in my_file.chunks():
            f.write(chunk)
        f.close()
        return HttpResponse("文件上传成功！")
    else:
        return HttpResponse("没发现文件！")


class List(ListView):
    # 设置模版文件
    template_name = 'student/list.html'
    # 设置模型外的数据
    extra_context = {'title': '学生信息列表'}
    # 查询结果集
    queryset = StudentInfo.objects.all()
    # 每页展示5条数据
    paginate_by = 5
    # 设置上下文对象名称
    context_object_name = 'student_list'


class Detail(DetailView):
    # 设置模版文件
    template_name = 'student/detail.html'
    # 设置模型外的数据
    extra_context = {'title': '学生信息详情'}
    # 设置查询模型
    model = StudentInfo
    # 设置上下文对象名称
    context_object_name = 'student'
    # 指定URL中用于获取对象的唯一标识符的参数名称，默认为’pk’。
    # pk_url_kwarg = 'id'


class Create(CreateView):
    # 设置模版文件
    template_name = 'student/create.html'
    # 设置模型外的数据
    extra_context = {'title': '学生信息添加'}
    # 指定form
    form_class = StudentForm
    # 执行成功后跳转地址
    success_url = '/student/list'


class Update(UpdateView):
    # 设置模版文件
    template_name = 'student/update.html'
    # 设置模型外的数据
    extra_context = {'title': '学生信息编辑'}
    # 设置查询模型
    model = StudentInfo
    # 指定form
    form_class = StudentForm
    # 执行成功后跳转地址
    success_url = '/student/list'


class Delete(DeleteView):
    # 设置模版文件
    template_name = 'student/delete.html'
    # 设置模型外的数据
    extra_context = {'title': '学生信息删除'}
    # 设置上下文对象名称
    context_object_name = 'student'
    # 设置查询模型
    model = StudentInfo
    # 执行成功后跳转地址
    success_url = '/student/list'


# 定义人类
class Person:
    # 属性 姓名
    name = None
    # 属性 年龄
    age = None

    def __init__(self, name, age):
        self.name = name
        self.age = age


def index(request):
    str = "hello"
    date = datetime.datetime.now()
    myDict = {"tom": '666', 'cat': '999', 'wzw': '333'}
    # 创建一个对象 zhangsan
    zhangsan = Person("张三", 21)
    myList = ["java", "python", "c"]
    myTuple = ("python", 222, 3.14, False)
    content_value = {"msg": str, "msg2": myDict, "msg3": zhangsan, "msg4":
        myList, "msg5": myTuple, "date": date}
    return render(request, 'index.html', context=content_value)


def to_course(request):
    """
    跳转课程页面
    :param request:
    :return:
    """
    return render(request, 'course.html')


def bookList(request):
    """
    图书列表查询
    """
    # 查询所有信息
    bookList = BookInfo.objects.all()
    print(bookList)

    # 查询所有信息
    bookList = BookInfo.objects.all()
    # 获取数据集的第一条数据的bookName属性值
    print(bookList[0].bookName)
    # 返回前2条数据 select * from t_book limit 2
    bookList = BookInfo.objects.all()[:2]
    print(bookList)
    # 查询指定字段
    bookList = BookInfo.objects.values("bookName", "price")
    print(bookList)
    # 查询指定字段 数据以列表方式返回，列表元素以元组表示
    bookList = BookInfo.objects.values_list("bookName", "price")
    print(bookList)

    # 获取单个对象，一般是根据id查询
    book = BookInfo.objects.get(id=2)
    print(book.bookName)

    # 返回满足条件id=2的数据，返回类型是列表
    bookList = BookInfo.objects.filter(id=2)
    bookList = BookInfo.objects.filter(price=100, id=1)
    # filter的查询条件可以设置成字典格式
    d = dict(price=100, id=1)
    bookList = BookInfo.objects.filter(**d)
    # SQL的or查询，需要引入Q，from django.db.models import Q
    # 语法格式：Q(field=value)|Q(field=value) 多个Q之间用"|"隔开
    bookList = BookInfo.objects.filter(Q(id=1) | Q(price=88))
    # SQL的不等于查询，在Q查询中用“~”即可
    # SQL select * from t_book where not (id=1)
    bookList = BookInfo.objects.filter(~Q(id=1))

    bookList = BookInfo.objects.all()
    content_value = {"title": "图书列表", "bookList": bookList}
    return render(request, 'book/list.html', context=content_value)


def preAdd(request):
    """
    预处理，添加操作
    :param request:
    :return:
    """
    bookTypeList = BookTypeInfo.objects.all()
    print(bookTypeList)
    content_value = {"title": "图书添加", "bookTypeList": bookTypeList}
    return render(request, 'book/add.html', context=content_value)


def preAdd2(request):
    """
    预处理，添加操作 使用form表单
    :param request:
    :return:
    """
    form = BookInfoForm()
    context_value = {"title": "图书添加", "form": form}
    return render(request, 'book/add2.html', context_value)


def preAdd3(request):
    """
    预处理，添加操作 使用modelForm表单
    :param request:
    :return:
    """
    form = BookInfoModelForm()
    context_value = {"title": "图书添加", "form": form}
    return render(request, 'book/add2.html', context_value)


def add(request):
    """
    图书添加
    :param request:
    :return:
    """
    # print(request.POST.get("bookName"))
    # print(request.POST.get("publishDate"))
    # print(request.POST.get("bookType_id"))
    # print(request.POST.get("price"))
    book = BookInfo()
    book.bookName = request.POST.get("bookName")
    book.publishDate = request.POST.get("publishDate")
    book.bookType_id = request.POST.get("bookType_id") or request.POST.get("bookType")
    book.price = request.POST.get("price")
    book.save()
    # 数据添加后，获取新增数据的主键id
    print(book.id)
    return bookList(request)


def preUpdate(request, id):
    """
    预处理，修改操作
    :param request:
    :return:
    """
    print("id:", id)
    book = BookInfo.objects.get(id=id)
    print(book)
    bookTypeList = BookTypeInfo.objects.all()
    print(bookTypeList)
    content_value = {"title": "图书修改", "bookTypeList": bookTypeList, "book":
        book}
    return render(request, 'book/edit.html', context=content_value)


def update(request):
    """
    图书修改
    :param request:
    :return:
    """
    book = BookInfo()
    book.id = request.POST.get("id")
    book.bookName = request.POST.get("bookName")
    book.publishDate = request.POST.get("publishDate")
    book.bookType_id = request.POST.get("bookType_id")
    book.price = request.POST.get("price")
    book.save()
    return bookList(request)


def delete(request, id):
    """
    图书删除
    :param request:
    :return:
    """
    # 删除所有数据
    # BookInfo.objects.all().delete()
    # 删除指定id数据
    BookInfo.objects.get(id=id).delete()
    # 根据条件删除多条数据
    # BookInfo.objects.filter(price__gte=90).delete()
    return bookList(request)


def transfer2(request):
    """
    模拟转账
    :param request:
    :return:
    """
    a1 = AccountInfo.objects.filter(user='张三')
    a1.update(account=F('account') + 100)
    a2 = AccountInfo.objects.filter(user='李四')
    a2.update(account=F('account') - 100 / 0)
    return HttpResponse("OK")


@transaction.atomic
def transfer(request):
    """
    模拟转账
    :param request:
    :return:
    """
    # 开启事务
    sid = transaction.savepoint()
    try:
        a1 = AccountInfo.objects.filter(user='张三')
        a1.update(account=F('account') + 100)
        a2 = AccountInfo.objects.filter(user='李四')
        a2.update(account=F('account') - 100 / 0)
        # 提交事务 （如不设置，当程序执行完成后，会自动提交事务）
        transaction.savepoint_commit(sid)
    except Exception as e:
        print("异常信息：", e)
        # 事务回滚
        transaction.savepoint_rollback(sid)
        return HttpResponse('转账失败')
    return HttpResponse("OK")
